﻿using log4net;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Reflection;
using WpfApp1.Acme.ApplicationAttribute;
using WpfApp1.Acme.ApplicationClass;
using WpfApp1.Acme.TemplateImpl;

namespace WpfApp1.Acme.Template {
    /// <summary>
    /// Bean工厂负责创建和获取Bean
    /// </summary>
    internal abstract class BeanFactory {
        /** bean注册池 */
        private static readonly ConcurrentDictionary<string, BeanDefinition> beanDefinitionMap = new ConcurrentDictionary<string, BeanDefinition>();
        /** bean单例池 */
        private static readonly ConcurrentDictionary<string, object> beanMap = new ConcurrentDictionary<string, object>();
        private static readonly ILog logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        /// <summary>
        /// 获取bean注册池
        /// </summary>
        /// <returns></returns>
        public static ConcurrentDictionary<string, BeanDefinition> getBeanDefinitionMap() { 
             return beanDefinitionMap; 
        }

        /// <summary>
        /// 获取bean单例池
        /// </summary>
        /// <returns></returns>
        public static ConcurrentDictionary<string, object> getBeanMap() {
            return beanMap;
        }

        /// <summary>
        /// 创建对象
        /// </summary>
        /// <param name="beanDefinition"></param>
        /// <returns></returns>
        public static object createBean(BeanDefinition beanDefinition) {
            BeanDefinition definition = beanDefinition;

            if (typeof(BeanInstantiation).IsAssignableFrom(beanDefinition.BeanType)) {
              definition = ((BeanInstantiation)ApplicationContext.getExecutingAssembly().CreateInstance(beanDefinition.BeanType.ToString())).beanInstantiationBefore(beanDefinition);
            }

            Assembly assembly = Assembly.GetExecutingAssembly();
            // 当前类实例化对象
            object bean = assembly.CreateInstance(definition.BeanType.ToString());

            if (typeof(BeanInstantiation).IsAssignableFrom(beanDefinition.BeanType)) {
                definition = ((BeanInstantiation)ApplicationContext.getExecutingAssembly().CreateInstance(beanDefinition.BeanType.ToString())).beanInstantiationAfter(beanDefinition);
            }

            FieldInfo[] fieldInfos = definition.BeanType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
            foreach (FieldInfo fieldInfo in fieldInfos) {

                // 是否有Autowired特性
                Attribute attribute = fieldInfo.GetCustomAttribute(typeof(Autowired));
                if (attribute != null) {
                    string beanName = attribute.GetType().GetProperty("BeanName").GetValue(attribute).ToString();
                    beanName = (beanName == "" ? fieldInfo.Name : beanName);
                    object fielValue = ApplicationContext.getBean(beanName);
                    fieldInfo.SetValue(bean, fielValue);
                }

            }
                return bean;
        }

        /// <summary>
        /// 实例化单例bean
        /// </summary>
        public static void instanceSingletionBean() {
            foreach (KeyValuePair<string, BeanDefinition> item in beanDefinitionMap) {

                if (ScopeType.singleton.Equals(item.Value.Scope)) {
                    bool isNoContainsBeanName = !beanMap.ContainsKey(item.Key);
                    if (isNoContainsBeanName) {
                        object bean = createBean(item.Value);
                        beanMap.TryAdd(item.Key, bean);
                    }
                }

            }
        }

    }
}
